package tau.dimes.util;

import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.regex.Pattern;

public class IPHelper 
{
	private static final String IPV4_REGEX = "\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b";
	private static final Pattern IPV4_PATTERN = Pattern.compile(IPV4_REGEX);
	
	public static String toNumericalString(String ipAddress)
	{
		if (ipAddress == null)
		{
			return "0";
		}
		
		String ipAddressTrimmed = ipAddress.trim();
		if (IPV4_PATTERN.matcher(ipAddressTrimmed).matches())
		{
			return canonicalToNumericalString(ipAddressTrimmed);
		}
		else
		{
			return longToNumericalString(ipAddressTrimmed);
		}
	}
	
	public static String toCanonicalString(String ipAddress)
	{
		if (ipAddress == null)
		{
			return "0.0.0.0";
		}
		
		String ipAddressTrimmed = ipAddress.trim();
		if (IPV4_PATTERN.matcher(ipAddressTrimmed).matches())
		{
			return ipAddressTrimmed;
		}
		else
		{
			return longToCanonicalString(ipAddressTrimmed);
		}
	}

	private static String canonicalToNumericalString(String ipAddressTrimmed)
	{
		try 
		{
			Inet4Address inet4Address = (Inet4Address)Inet4Address.getByName(ipAddressTrimmed);
			byte[] byteArray = inet4Address.getAddress();
			BigInteger bigInteger = new BigInteger(1, byteArray);
			return bigInteger.toString();
		} catch (UnknownHostException e) 
		{
		}

		return "0";
	}

	private static String longToNumericalString(String ipAddressTrimmed) 
	{
		try
		{
			Long longAddress = new Long(ipAddressTrimmed);
			if (longAddress >= 0 && longAddress <= 0xFFFFFFFFL)
			{
				return longAddress.toString();
			}
		}
		catch (NumberFormatException e)
		{
		}

		return "0";
	}

	private static String longToCanonicalString(String ipAddressTrimmed) 
	{
		try
		{
			Long longAddress = new Long(ipAddressTrimmed);
			if (longAddress >= 0 && longAddress <= 0xFFFFFFFFL)
			{
				byte[] byteArray = BigInteger.valueOf(longAddress).toByteArray();
				byte[] fixedByteArray;
				
				if (byteArray.length >= 4)
				{
					fixedByteArray = Arrays.copyOfRange(byteArray, byteArray.length - 4, byteArray.length);
				}
				else
				{
					fixedByteArray = new byte[4];
					Arrays.fill(fixedByteArray, (byte)0);
					System.arraycopy(byteArray, 0, fixedByteArray, 4 - byteArray.length, byteArray.length);
				}
				
				Inet4Address inet4Address = (Inet4Address)Inet4Address.getByAddress(fixedByteArray);
				return inet4Address.getHostAddress();
			}
		}
		catch (NumberFormatException e)
		{
		} 
		catch (UnknownHostException e) 
		{
		}

		return "0.0.0.0";
	}
}
